package com.cskaoyan.wordmemorize.common.aspect.operate;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.SaTokenException;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.common.exception.ExcelParseException;
import com.cskaoyan.wordmemorize.common.util.JsonUtil;
import com.cskaoyan.wordmemorize.dao.entity.OperateLogDO;
import com.cskaoyan.wordmemorize.dao.mapper.OperateLogMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@Aspect
public class OperateAspect {

    @Autowired
    OperateLogMapper operateLogMapper;


    @Pointcut("@annotation(com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog)")
    public void countTime() {
    }

    //日志操作
    @Around(value = "countTime()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("before");

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取注解信息
        OperateLog operateLog = method.getAnnotation(OperateLog.class);
        if (operateLog == null) {
            operateLog = joinPoint.getTarget().getClass().getAnnotation(OperateLog.class);
        }
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        Object ret = null;
        int status = 1;
        OperateLogDO build = OperateLogDO.builder()
                .employeeId(StpKit.ADMIN.getLoginIdAsLong())
                .operateType(operateLog.operateType())
                .dataType(operateLog.dateType())
                .createTime(Timestamp.valueOf(LocalDateTime.now()))
                .build();

        try {
            // 目标方法执行
            ret = joinPoint.proceed(args);

        } catch (Exception e) {
            status = 0;
            OperateAspect.throwSpecificException(e);
        } finally {
            build.setStatus(status);

            switch (operateLog.operateType()) {
                case OperateLogConstant.OPERATE_ADD:
                case OperateLogConstant.OPERATE_UPDATE:
                case OperateLogConstant.OPERATE_UPDATE_STATUS:
                    // 修改操作：提取并记录修改对象
                    build.setData(JsonUtil.toJSON(args));
                    break;
                case OperateLogConstant.OPERATE_EXCEL_ADD:
                case OperateLogConstant.OPERATE_SINGLE_DELETE:
                case OperateLogConstant.OPERATE_BATCH_DELETE:
                    System.out.println("以下是删除对象"+ret);
                    build.setData(JsonUtil.toJSON(ret));
                    break;

            }
            System.out.println(build);

            operateLogMapper.insert(build);

        }

        return ret;
    }

    private static void throwSpecificException(Throwable e) {

        if (e instanceof NotLoginException) {
            throw (NotLoginException) e;
        }
        if (e instanceof NotPermissionException) {
            throw (NotPermissionException) e;
        }
        if (e instanceof SaTokenException) {
            throw (SaTokenException) e;
        }
        if (e instanceof ExcelParseException) {
            throw (ExcelParseException) e;
        }
        if (e instanceof BusinessException) {
            throw (BusinessException) e;
        }
        throw new RuntimeException(e);
    }
}
